package com.wb3.meta.common.authentication;

import com.alibaba.fastjson.JSONObject;
import com.wb3.meta.common.annotation.NoPermission;
import com.wb3.meta.common.annotation.RequireAuth;
import com.wb3.meta.common.enums.EnumConstants;
import com.wb3.meta.common.exceptions.AuthException;
import com.wb3.meta.common.utils.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

@Slf4j
@Component
public class AuthorizationInterceptor implements HandlerInterceptor {
    public static final String LOGIN_TOKEN_KEY = "token";
    public static final String LOGIN_UUID_KEY = "uuid";
    public static final List<String> ignoreUrlList = new ArrayList<>();

    static {
        ignoreUrlList.add("/test/");
        ignoreUrlList.add("/error");
        ignoreUrlList.add("/wx/user/login");
    }
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        String url = request.getRequestURI();
        log.debug("请求url：{}",url);
//        IgnoreAuth annotation;
//        if (handler instanceof HandlerMethod) {
//            annotation = ((HandlerMethod) handler).getMethodAnnotation(IgnoreAuth.class);
//        } else {
//            return true;
//        }


        //不允许访问接口
        NoPermission noPermission;
        if (handler instanceof HandlerMethod) {
            noPermission = ((HandlerMethod) handler).getMethodAnnotation(NoPermission.class);
            //如果@NoPermission != null，则没有权限访问接口
            if (noPermission != null) {
                throw new AuthException(401,"无权限"); // 401
            }
        }

        String uuid = request.getHeader(LOGIN_UUID_KEY);
        RequireAuth annotation = null;
        if (handler instanceof HandlerMethod) {
            annotation = ((HandlerMethod) handler).getMethodAnnotation(RequireAuth.class);
        }

        //如果@RequireAuth == null，则不需要验证token
        if (annotation == null) {
            return true;
        }

        //如果是登录 or登出 直接放行
//        if (ignore(url)) {
//            return true;
//        }
        //从header中获取token
        String token = request.getHeader(LOGIN_TOKEN_KEY);
        //如果header中不存在token，则从参数中获取token
        if (StringUtils.isBlank(token)) {
            token = request.getParameter(LOGIN_TOKEN_KEY);
        }

        //token为空
        if (StringUtils.isBlank(token) && annotation.forced()) {
            throw new AuthException(401,"请先登录"); // 401
//            log.error("请先登录");
//            return false;
        }
//
//        if(StringUtils.isBlank(token)) {
//            return true;
//        }

        //查询token信息
        String jwt = JwtUtil.decryptJWT(token);
        if (StringUtils.isBlank(jwt) && !ignore(url)) {
            throw new AuthException(401,"请先登录");
//            log.error("无效的token");
//            return false;
        }

        //设置userId到request里，后续根据userId，获取用户信息
        AuthAddress authAddress = JSONObject.parseObject(jwt, AuthAddress.class);
        assert authAddress != null;
        authAddress.setToken(token);
        RequestHolder.setAuthAddress(authAddress);
        return true;
    }

    public void afterCompletion(HttpServletRequest request
            , HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
        RequestHolder.clear(); // 清除线程信息
    }
    /**
     * @Author RP
     * @Description //TODO 校验请求url是否在忽略列表里
     * @Date 0:02 2022/5/27
     * @Param [path]
     * @return boolean
     **/
    private boolean ignore(String path) {
        return ignoreUrlList.stream()
                .map(url -> url.replace("/**", ""))
                .anyMatch(path::startsWith);
    }

}
